/*
 * bg_server.c
 *
 *  Created on: 2022年1月6日
 *      Author: young
 */

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<signal.h>
#include<pthread.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<arpa/inet.h>
#include "wwan.h"

#define UNIX_SOCKET_PATH "cm_syllament"

static int sock_fd;
static struct sockaddr_un cltsock;
/*
*struct sockaddr_un 
*	{
*   	sa_family_t sun_family; // 地址族，通常为AF_UNIX
*    	char sun_path[108];     // 套接字路径名
*	};
*/

static int startServer()
{
	struct sockaddr_un serv_unadr;
	int sock_fd, flag, ret;

	signal(SIGPIPE, SIG_IGN);//忽略SIGPIPE信号，防止程序在写入已关闭的管道时终止
	unlink(UNIX_SOCKET_PATH);//删除指定路径下的文件

	sock_fd = socket(AF_UNIX, SOCK_DGRAM, 0);//AF_UNIX：用于在同一台计算机上的进程之间进行通信。
	if(sock_fd < 0)
		return -1;

	flag = 1;
	
	setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int));
	/*
	*SOL_SOCKET：表示这是一个套接字级别的选项
	*SO_REUSEADDR：允许在绑定套接字时重用处于TIME_WAIT状态的地址和端口
	*/

	bzero(&serv_unadr, sizeof(struct sockaddr_un));
	serv_unadr.sun_family = AF_UNIX;
	strcpy(serv_unadr.sun_path, UNIX_SOCKET_PATH);

	ret = bind(sock_fd, (struct sockaddr *)&serv_unadr, sizeof(struct sockaddr));
	if(ret){
		close(sock_fd);
		return -1;
	}

	return sock_fd;
}

void *server_notify(void *arg)//notification
{
	static char    last_imei[32] = {'\0'};
	static char    last_iccid[32] = {'\0'};
	static int     last_ns = 0;
	static uint8_t last_sq = 0;

	int		my_ns;
	char	str[64];
	uint8_t	cnt = 0;

	pthread_detach(pthread_self());

	while(1)
	{
		if(wwan_is_ok())
		{
			switch(ns)
			{
				case -3:
				case -2:
				case -1: my_ns = ns;break;
				default: my_ns = wwan_is_online() + 1;break;
			}
		}else
			my_ns = 0;

			if( cnt >= 15 					||
				strcmp(imei, last_imei) 	||
				strcmp(iccid, last_iccid) 	||
				my_ns != last_ns			||
				sq != last_sq
				)
				{
					snprintf(str, sizeof(str), "status:%s,%s,%d,%u#", imei, iccid, my_ns, sq);
					sendto(sock_fd, str, strlen(str), 0, (struct sockaddr *)&cltsock, sizeof(struct sockaddr));

					cnt = 0;
					strcpy(last_imei, imei);
					strcpy(last_iccid, iccid);
					last_ns = my_ns;
					last_sq = sq;
				}

		sleep(1);
		cnt ++;
	}

	return NULL;
}

void *server_mon(void *arg)//monitoring
{
	socklen_t socklen = sizeof(struct sockaddr_un);
	pthread_t tid;
	int       ret;
	uint8_t   buf[255];

	pthread_detach(pthread_self());//将线程设置为分离状态，资源会在线程退出时自动释放

	sock_fd = startServer();
	if(sock_fd < 0){
		printf("bg_server start failed!\n");
		goto end;
	}

	pthread_create(&tid, NULL, server_notify, NULL);

	while(1)
	{
		ret = recvfrom(sock_fd, buf, sizeof(buf), 0, (struct sockaddr *)&cltsock, &socklen);
		if(ret > 0){
			buf[ret] = '\0';
			if(strstr((char *)buf, "offline"))
				wwan_offline();
		}else
			break;
	}
end:
	return NULL;
}

void start_bg_server()
{
	pthread_t tid;

	pthread_create(&tid, NULL, server_mon, NULL);
}
